package znet

import (
	"fmt"
	"net"
	ziface "zinx/Ziface"
	"zinx/utlis"

)

// IServer的接口实现
type Server struct {
	Name      string //服务器名称
	IPVersion string
	IP        string
	port      int

	//当前的Server添加一个router,server注册的链接对应的处理业务
	//路由模块
	MsgHandler ziface.IMsgHandler

	ConManager ziface.IConManager


	//该Server,创建链接只会自动调用的Hook函数--OnConnStart
	OnConnStart func(conn ziface.IConnection)
	//该Server,销毁链接自动调用的Hook函数--OnConnStop
	OnConnStop func(conn ziface.IConnection)

}

// 启动服务器
func (s *Server) Start() {
	//获取一个TCP的addr
	fmt.Printf("[Zinx] Server Listenner at IP:%s,Port:%d is starting\n", utlis.GlovbalObject.Host, utlis.GlovbalObject.TcpPort)
	fmt.Printf(" [Zinx] Version %s,MaxConn :%d ,MaxPackeetSize:%d\n", utlis.GlovbalObject.Version, utlis.GlovbalObject.MaxConn, utlis.GlovbalObject.MaxPackageSize)


	
	go func() {
		
		//开启消息队列和工程池
		s.MsgHandler.StartWorkerPool()

		
		//创建TcpAddr
		addr, err := net.ResolveTCPAddr(s.IPVersion, fmt.Sprintf("%s:%d", s.IP, s.port))
		if err != nil {
			fmt.Println("resolve tcp addt error: ", err)
			return
		}
		//listen
		listener, err := net.ListenTCP(s.IPVersion, addr)
		if err != nil {
			fmt.Println("listen tcp error: ", err)
			return
		}

		fmt.Println("start Zinx server sucess:", s.Name, "sucess Listenning...")
		var connid uint32
		connid = 0
		//accept
		for {
			conn, err := listener.AcceptTCP()
			if err != nil {
				fmt.Println("Accept err", err)
				continue
			}

			//判断连接是否达到最大，如果超过最大数量，就关闭此连接
			if s.ConManager.Len()>=utlis.GlovbalObject.MaxConn{
				fmt.Println("over Maxconn size ,Maxcon=",utlis.GlovbalObject.MaxConn)
				conn.Close()
				continue
			}
			connid++
			//提取一个链接，就创建一个Connection
			dealconn := NewConnection(s,conn, connid, s.MsgHandler)

			go dealconn.Start()
		}
	}()

}

// 停止服务器
func (s *Server) Stop() {
	fmt.Println("[Stop] zinx.....")
	//回收资源
	s.ConManager.ClearConn()
}

// 运行服务器
func (s *Server) Serve() {
	s.Start()
	//设置为阻塞状态,防止主线程结束，导致s.Start协程介绍
	select {}
}



//返回连接管理
func(s* Server) GetConnManger() ziface.IConManager {
	return s.ConManager
}

// 添加路由方法
func (s *Server) AddRouter(msgid uint32,router ziface.IRouter) {
	s.MsgHandler.AddRouter(msgid,router)
	fmt.Println("Add Router Sucess")

}

/*
初始化Server模块的方法
*/
func NewServer() ziface.IServer {

	s := &Server{
		Name:      utlis.GlovbalObject.Name,
		IPVersion: "tcp4",
		IP:        utlis.GlovbalObject.Host,
		port:      utlis.GlovbalObject.TcpPort,
		MsgHandler:    NewMsgHandler(),
		ConManager: NewConManger(),
	}

	return s
}


func(s *Server)SetOnConnStart(f func(conn ziface.IConnection)){
	s.OnConnStart=f
}

func(s *Server)SetOnConnStop(f func(conn ziface.IConnection)){

	s.OnConnStop=f
}

func(s *Server)CallOnConnStart(conn ziface.IConnection){
	
	if s.OnConnStart!=nil{
		fmt.Println("--->Call onConnStart<---")
		s.OnConnStart(conn)
	}

}

func(s *Server)CallOnConnStop(conn ziface.IConnection){
	if s.OnConnStop!=nil{
		fmt.Println("--->Call onConnStop<---")
		s.OnConnStop(conn)
	}

}